/**
 * Copyright © 2011 Creativor Studio.
 * About license information, please see LICENSE.txt.
 */
package org.creativor.rayson.transport.stream;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import org.creativor.rayson.api.TransferSocket;
import org.creativor.rayson.transport.api.TimeLimitConnection;

// TODO: Auto-generated Javadoc
/**
 * An abstract implement of {@link TransferSocket}.
 * 
 * @author Nick Zhang
 */
public abstract class AbstractTransferSocket implements TransferSocket
{
	private DataInput dataInput;
	private DataOutput dataOutput;
	private Socket socket;
	private short code;
	private short clientVersion;
	private byte connectionVersion;
	
	/**
	 * Instantiates a new abstract transfer socket.
	 * 
	 * @param connection
	 *            the connection
	 * @param socket
	 *            the socket
	 * @param code
	 *            the code
	 * @param clientVersion
	 *            the client version
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	protected AbstractTransferSocket(TimeLimitConnection connection, Socket socket, short code,
			short clientVersion) throws IOException
	{
		this.socket = socket;
		this.clientVersion = clientVersion;
		this.connectionVersion = connection.getVersion();
		this.code = code;
		this.dataInput =
				new DataInputImpl(new DataInputStream(this.socket.getInputStream()), this,
						connection);
		this.dataOutput =
				new DataOutputImpl(new DataOutputStream(this.socket.getOutputStream()), this,
						connection);
	}
	
	/**
	 * Gets the connection version.
	 * 
	 * @return the connection version
	 */
	@Override
	public final byte getConnectionVersion()
	{
		return connectionVersion;
	}
	
	/**
	 * Close.
	 * 
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	@Override
	public  void close() throws IOException
	{
		this.socket.close();
	}
	
	/**
	 * Gets the data input.
	 * 
	 * @return the data input
	 */
	@Override
	public DataInput getDataInput()
	{
		return dataInput;
	}
	
	/**
	 * Gets the data output.
	 * 
	 * @return the data output
	 */
	@Override
	public DataOutput getDataOutput()
	{
		return dataOutput;
	}
	
	/**
	 * Gets the local addr.
	 * 
	 * @return the local addr
	 */
	@Override
	public SocketAddress getLocalAddr()
	{
		return socket.getLocalSocketAddress();
	}
	
	/**
	 * Gets the remote addr.
	 * 
	 * @return the remote addr
	 */
	@Override
	public SocketAddress getRemoteAddr()
	{
		return socket.getRemoteSocketAddress();
	}
	
	/**
	 * Gets the code.
	 * 
	 * @return the code
	 */
	@Override
	public final short getCode()
	{
		return code;
	}
	
	/**
	 * Gets the client version.
	 * 
	 * @return the client version
	 */
	@Override
	public final short getClientVersion()
	{
		return clientVersion;
	}
	
	/**
	 * Checks if is closed.
	 * 
	 * @return true, if is closed
	 */
	@Override
	public boolean isClosed()
	{
		return socket.isClosed();
	}
	
	/**
	 * Checks if is input shutdown.
	 * 
	 * @return true, if is input shutdown
	 */
	@Override
	public boolean isInputShutdown()
	{
		return socket.isInputShutdown();
	}
	
	/**
	 * Checks if is output shutdown.
	 * 
	 * @return true, if is output shutdown
	 */
	@Override
	public boolean isOutputShutdown()
	{
		return socket.isOutputShutdown();
	}
	
	@Override
	public  void setTimeout(int timeout) throws SocketException
	{
		this.socket.setSoTimeout(timeout);
	}
	
	@Override
	public int getTimeout() throws SocketException
	{
		return this.socket.getSoTimeout();
	}
	
	/**
	 * Shutdown input.
	 * 
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	@Override
	public void shutdownInput() throws IOException
	{
		this.socket.shutdownInput();
	}
	
	/**
	 * Shutdown output.
	 * 
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	@Override
	public void shutdownOutput() throws IOException
	{
		this.socket.shutdownOutput();
	}
	
	/**
	 * To string.
	 * 
	 * @return the string
	 */
	@Override
	public String toString()
	{
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("code: ");
		sb.append(this.code);
		sb.append(", ");
		sb.append("connection version: ");
		sb.append(this.connectionVersion);
		sb.append(", ");
		sb.append("client version: ");
		sb.append(this.clientVersion);
		sb.append(", ");
		sb.append("socket: ");
		sb.append(this.socket.toString());
		sb.append("}");
		return sb.toString();
	}
}
